#include "page.h"
#include <cstring>
#include <stdexcept>
#include <iostream>

/**
 * @brief 默认构造函数
 */
Page::Page() {
    reset(); // 初始化页状态
}

/**
 * @brief 带页ID的构造函数
 * @param page_id 页的唯一标识符
 */
Page::Page(page_id_t page_id) {
    reset();
    header_.page_id = page_id;
}

/**
 * @brief 获取页ID
 * @return 页的唯一标识符
 */
page_id_t Page::get_page_id() const {
    return header_.page_id;
}

/**
 * @brief 设置页ID
 * @param page_id 新的页ID
 */
void Page::set_page_id(page_id_t page_id) {
    header_.page_id = page_id;
}

/**
 * @brief 获取页数据的原始指针，只读
 * @return 指向页数据区的常量指针
 */
const char* Page::get_data() const {
    return data_;
}

/**
 * @brief 获取页数据的可修改指针
 * @return 指向页数据区的指针
 */
char* Page::get_data() {
    return data_;
}

/**
 * @brief 获取页数据的大小
 * @return 页数据区大小
 */
size_t Page::get_data_size() const {
    return sizeof(data_);
}

/**
 * @brief 检查页是否为脏页（已被修改）
 * @return true如果是脏页，false否则
 */
bool Page::is_dirty() const {
    return header_.is_dirty;
}

/**
 * @brief 标记页为脏页
 */
void Page::mark_dirty() {
    header_.is_dirty = true;
}

/**
 * @brief 标记页为干净页
 */
void Page::mark_clean() {
    header_.is_dirty = false;
}

/**
 * @brief 增加pin计数（页正在被使用）
 * @return 新的pin计数值
 */
int Page::pin_count() {
    return ++header_.pin_count;
}

/**
 * @brief 减少pin计数（页使用结束）
 * @return 新的pin计数值
 */
int Page::unpin_count() {
    if (header_.pin_count > 0) {
        return --header_.pin_count;
    }
    return 0;
}

/**
 * @brief 获取当前pin计数
 * @return pin计数值
 */
int Page::get_pin_count() const {
    return header_.pin_count;
}

/**
 * @brief 检查页是否被pin（是否正在被使用）
 * @return true如果pin计数>0，false否则
 */
bool Page::is_pinned() const {
    return header_.pin_count > 0;
}

/**
 * @brief 重置页状态
 * 清除所有数据，重置为初始状态
 */
void Page::reset() {
    // 重置页头
    header_.page_id = INVALID_PAGE_ID;
    header_.pin_count = 0;
    header_.is_dirty = false;
    header_.checksum = 0;
    header_.free_space_offset = 0;
    header_.slot_count = 0;
    
    // 清空数据区
    std::memset(data_, 0, sizeof(data_));
}

/**
 * @brief 从另一个页复制数据
 * @param other 源页
 */
void Page::copy_from(const Page& other) {
    if (this == &other) {
        return; // 自赋值检查
    }
    
    // 复制页头（除了pin_count和is_dirty状态）
    page_id_t old_page_id = header_.page_id;
    int old_pin_count = header_.pin_count;
    bool old_dirty = header_.is_dirty;
    
    header_ = other.header_;
    
    // 恢复状态字段
    header_.page_id = old_page_id;    // 保持原有页ID
    header_.pin_count = old_pin_count; // 保持原有pin计数
    header_.is_dirty = old_dirty;     // 保持原有脏页状态
    
    // 复制数据
    std::memcpy(data_, other.data_, sizeof(data_));
    
    // 标记为脏页（因为内容被修改了）
    mark_dirty();
}

/**
 * @brief 将数据复制到指定内存位置
 * @param dest 目标内存地址
 * @param size 要复制的字节数
 * @param offset 页内的偏移量
 * @return 实际复制的字节数
 */
size_t Page::copy_to(void* dest, size_t size, size_t offset) const {
    if (dest == nullptr) {
        throw std::invalid_argument("Destination pointer cannot be null");
    }
    
    if (offset >= sizeof(data_)) {
        return 0; // 偏移量超出范围
    }
    
    // 计算实际可复制的字节数
    size_t bytes_available = sizeof(data_) - offset;
    size_t bytes_to_copy = (size < bytes_available) ? size : bytes_available;
    
    std::memcpy(dest, data_ + offset, bytes_to_copy);
    return bytes_to_copy;
}

/**
 * @brief 从指定内存位置复制数据到页
 * @param src 源内存地址
 * @param size 要复制的字节数
 * @param offset 页内的偏移量
 * @return 实际复制的字节数
 */
size_t Page::copy_from(const void* src, size_t size, size_t offset) {
    if (src == nullptr) {
        throw std::invalid_argument("Source pointer cannot be null");
    }
    
    if (offset >= sizeof(data_)) {
        return 0; // 偏移量超出范围
    }
    
    // 计算实际可复制的字节数
    size_t bytes_available = sizeof(data_) - offset;
    size_t bytes_to_copy = (size < bytes_available) ? size : bytes_available;
    
    std::memcpy(data_ + offset, src, bytes_to_copy);
    
    // 标记为脏页（因为内容被修改了）
    mark_dirty();
    
    return bytes_to_copy;
}

/**
 * @brief 比较两个页的数据是否相同
 * @param other 另一个页
 * @return true如果数据相同，false否则
 */
bool Page::data_equals(const Page& other) const {
    if (this == &other) {
        return true; // 同一个对象
    }
    
    // 比较数据区内容
    return std::memcmp(data_, other.data_, sizeof(data_)) == 0;
}